package main

import (
	"os"
	"path/filepath"
	"strings"
	"time"

	"gitee.com/smewl13/beehive/internal/notice"
	"gitee.com/smewl13/beehive/internal/queryip"
	"gitee.com/smewl13/beehive/pkg/config"
	"gitee.com/smewl13/beehive/pkg/lpath"
	"gitee.com/smewl13/beehive/pkg/zaplog"
	"github.com/spf13/viper"
	"github.com/urfave/cli/v2"
	"go.uber.org/zap"
)

const (
	MailTpl = `<h2>%s</h2>
	当前公网IP地址: <font color="comment">%s</font>`

	WXWorkTpl = `{
	        "msgtype": "markdown",
	        "markdown": {
	            "content": "***%s***\n
				>当前公网IP地址:\t<font color=\"comment\">%s</font>"
	        }
	   }`
)

var (
	workDir, _ = lpath.GetRootPath()
	dataDir    = filepath.Join(workDir, "data")
	cacheFile  = filepath.Join(dataDir, "ip.txt")
)

func NewAPP(ctx *cli.Context) *APP {
	file := ctx.String("config")
	conf := config.NewConfig(file)
	logger := zaplog.NewLogger(zaplog.NewLog(conf))
	infoConfig, _ := conf.Get("puship.website").([]any)
	interval := strings.TrimSpace(conf.GetString("puship.interval"))
	dur, err := config.ParseDuration(interval)
	if err != nil {
		logger.Error(
			"[初始化]加载配置IP查询频率解析失败",
			zap.String("interval", interval),
			zap.Error(err),
		)
		dur = config.Duration(time.Minute * 5)
	}

	app := &APP{
		logger:   logger,
		interval: time.Duration(dur),
		query:    make([]*queryip.QueryIP, 0, len(infoConfig)),
		notice:   notice.NewNotice(logger, conf),
	}
	app.init()
	app.loadCache()
	switch app.notice.Name() {
	case "wxwork":
		app.notice.SetTpl(WXWorkTpl)
	case "mail":
		app.notice.SetTpl(MailTpl)
	}

	infoConf := viper.New()
	for _, value := range infoConfig {
		infoConf.Set("website", value)
		app.query = append(app.query, queryip.NewQueryIP(logger, infoConf))
	}

	return app
}

type APP struct {
	ip       string
	preIP    string
	interval time.Duration
	query    []*queryip.QueryIP
	notice   notice.Noticer
	logger   *zap.Logger
}

func (a *APP) Run() {
	for {
		func() {
			a.queryIP()
			if len(a.ip) == 0 {
				a.logger.Error("[公网IP查询]未获取到IP")
				return
			}

			a.logger.Info("[公网IP查询]", zap.String("ip", a.ip))
			if a.ip == a.preIP {
				return
			}

			a.logger.Info(
				"[公网IP查询]ip变化",
				zap.String("old_ip", a.preIP),
				zap.String("new_ip", a.ip),
			)

			a.notice.Send(a.ip)
			if !a.notice.Status() {
				return
			}
			a.preIP = a.ip
			a.writeCache()
		}()
		time.Sleep(a.interval)
	}
}

func (a *APP) loadCache() {
	buf, err := os.ReadFile(cacheFile)
	if err != nil {
		a.logger.Error(
			"[缓存IP]读取缓存文件失败", zap.String("file", cacheFile), zap.Error(err),
		)
	}
	a.preIP = strings.TrimSpace(string(buf))
}

func (a *APP) writeCache() {
	if err := lpath.WriteFile(cacheFile, []byte(a.ip)); err != nil {
		a.logger.Error(
			"[缓存IP]写入缓存文件失败", zap.String("file", cacheFile), zap.Error(err),
		)
	}
}

func (a *APP) queryIP() {
	for _, info := range a.query {
		info.Handle()
		if !info.Status || len(info.IP) == 0 {
			continue
		}
		a.ip = info.IP
		return
	}
}

func (a *APP) init() {
	if err := lpath.MkdirAll(dataDir); err != nil {
		a.logger.Fatal(
			"[初始化]创建数据目录失败", zap.String("path", dataDir), zap.Error(err),
		)
	}
}
